from flask import Flask, render_template, request, redirect, url_for, flash,session,jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from config import Config
from models import User 
from datetime import datetime, timedelta
import os
from models import db, Group

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
# 数据库模型
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    # 关联消息、预约和团体
    messages = db.relationship('Message', backref='user', lazy=True)
    appointments = db.relationship('Appointment', backref='user', lazy=True)
    groups = db.relationship('Group', backref='user', lazy=True)


class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    idcard = db.Column(db.String(18), unique=True, nullable=False)
    type = db.Column(db.String(20), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)  # 关联用户ID
class ScenicSpot(db.Model):
    __tablename__ = 'scenic_spots'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    image_url = db.Column(db.String(255), nullable=False)
    is_favorited = db.Column(db.Boolean, default=False)

class Appointment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    spot_id = db.Column(db.Integer, db.ForeignKey('scenic_spots.id'), nullable=False)
    date = db.Column(db.Date, nullable=False)
    time = db.Column(db.String(20), nullable=False)
    traveler_name = db.Column(db.String(255), nullable=False)
    id_card = db.Column(db.String(18), nullable=False)
    ticket_type = db.Column(db.String(50), nullable=False)
    status = db.Column(db.String(20), default="预约中")
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)


class Group(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    spot_id = db.Column(db.Integer, nullable=False)  # 对应景点 ID
    team_size = db.Column(db.Integer, nullable=False)  # 团队人数
    contact_name = db.Column(db.String(255), nullable=False)  # 联系人姓名
    contact_phone = db.Column(db.String(20), nullable=False)  # 联系人电话
    excel_file = db.Column(db.String(255), nullable=True)  # 上传的 Excel 文件路径
    date = db.Column(db.Date, nullable=False, default='1970-01-01')
    time = db.Column(db.String(20), nullable=False, default="6:00-12:00")
    # 外键关联用户
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

app.config['UPLOAD_FOLDER'] = os.path.join(os.getcwd(), 'uploads')

# 设置允许上传的文件类型（可选）
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif', 'xlsx', 'xls'}

# 创建 uploads 文件夹（如果不存在）
if not os.path.exists(app.config['UPLOAD_FOLDER']):
    os.makedirs(app.config['UPLOAD_FOLDER'])
@app.route('/')
def index():
    return redirect(url_for('login'))
# 路由：主页（登录）
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')  # 获取用户输入的账号
        password = request.form.get('password')  # 获取用户输入的密码
        
        # 查询数据库中是否存在该账号
        user = User.query.filter_by(username=username).first()
        message = ""

        # 判断账号是否存在
        if not user:
            message = '账号不存在！'
        else:
            # 判断密码是否匹配
            if not check_password_hash(user.password, password):
                message = '密码错误！'
            else:
                # 账号和密码均匹配，允许登录
                session['user_id'] = user.id  # 存储用户 ID 到 session
                flash('登录成功！', 'success')
                return redirect(url_for('home'))
        
        return render_template('login.html', message=message)

    # GET 请求时渲染登录页面
    return render_template('login.html')


# 注册页面
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')  # 新增邮箱输入
        password = request.form.get('password')
        confirm_password = request.form.get('confirm_password')

        # 输入验证逻辑
        if not email:
            flash('邮箱不能为空！', 'danger')
        elif password != confirm_password:
            flash('两次密码输入不一致！', 'danger')
        elif User.query.filter_by(username=username).first():
            flash('该账号已存在！', 'danger')
        else:
            # 保存新用户到数据库
            hashed_password = generate_password_hash(password)
            new_user = User(username=username, password=hashed_password, email=email)
            db.session.add(new_user)
            db.session.commit()
            flash('注册成功！请登录。', 'success')
            return redirect(url_for('login'))
    return render_template('register.html')


# 忘记密码页面
@app.route('/forget', methods=['GET', 'POST'])
def forget():
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')

        # 1. 查找用户是否存在
        user = User.query.filter_by(username=username).first()
        if not user:
            flash('账号不存在！', 'danger')
            return render_template('forget.html')

        # 2. 判断邮箱是否与账号匹配
        if user.email != email:
            flash('邮箱输入错误！', 'danger')
            return render_template('forget.html')

        # 3. 判断两次密码是否一致
        if new_password != confirm_password:
            flash('两次密码输入不一致！', 'danger')
            return render_template('forget.html')

        # 更新用户密码
        user.password = generate_password_hash(new_password)
        db.session.commit()
        flash('密码已重置，请重新登录。', 'success')
        return redirect(url_for('login'))

    return render_template('forget.html')


# 路由：主页
@app.route('/home')
def home():
    return render_template('home.html')

@app.route('/tickets')
def tickets():
    # 获取当前用户的所有消息
    user_id = session.get('user_id')
    user = User.query.get(user_id)
    if user:
        spots = ScenicSpot.query.all()  # 从数据库中获取所有景点
        user_messages = user.messages  # 获取当前用户的消息
        return render_template('ticket.html', spots=spots, user_messages=user_messages)
    else:
        flash('用户未登录')
        return redirect(url_for('login'))

# 路由：切换收藏状态
@app.route('/toggle-favorite/<int:spot_id>', methods=['POST'])
def toggle_favorite(spot_id):
    spot = ScenicSpot.query.get_or_404(spot_id)  # 从数据库中获取景点
    spot.is_favorited = not spot.is_favorited  # 切换收藏状态
    db.session.commit()  # 提交数据库修改
    return jsonify({"success": True})

# 路由：显示具体景区详情
@app.route('/ticket_sure/<int:spot_id>', methods=['GET', 'POST'])
def ticket_sure(spot_id):
    user_id = session.get('user_id')
    user = User.query.get(user_id)
    if not user:
        flash('用户未登录')
        return redirect(url_for('login'))
    
    spot = ScenicSpot.query.filter_by(id=spot_id).first()
    if not spot:
        flash('未找到景区')
        return redirect(url_for('tickets'))

    today = datetime.now()
    available_dates = [(today + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(7)]
    time_slots = ['6:00-12:00', '12:00-17:00']

    if request.method == 'POST':
        selected_date = request.form.get('date')
        selected_time = request.form.get('time')
        selected_messages = request.form.getlist('messages')

        if selected_date and selected_time and selected_messages:
            for message_id in selected_messages:
                selected_message = Message.query.filter_by(id=message_id, user_id=user.id).first()  # 确保消息属于当前用户
                if selected_message:
                    appointment = Appointment(
                        spot_id=spot.id,
                        date=selected_date,
                        time=selected_time,
                        traveler_name=selected_message.name,
                        id_card=selected_message.idcard,
                        ticket_type=selected_message.type,
                        user_id=user.id  # 关联当前用户
                    )
                    db.session.add(appointment)
            db.session.commit()
            flash('预约成功')
            return redirect(url_for('tickets'))
        else:
            flash('请选择时间和旅客信息')

    # 获取当前用户的所有消息
    user_messages = user.messages
    return render_template('ticket_sure.html', spot=spot, available_dates=available_dates, time_slots=time_slots, messages=user_messages)



@app.route('/groups')
def groups():
    user_id = session.get('user_id')
    user = User.query.get(user_id)
    if user:
        spots = ScenicSpot.query.all()
        user_groups = user.groups  # 获取当前用户的团体信息
        return render_template('groups.html', spots=spots, user_groups=user_groups)
    else:
        flash('用户未登录')
        return redirect(url_for('login'))

# 景区预约页面
@app.route('/group_sure/<int:spot_id>', methods=['GET', 'POST'])
def group_sure(spot_id):
    user_id = session.get('user_id')
    user = User.query.get(user_id)
    if not user:
        flash('用户未登录')
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        date = request.form.get('date')
        time = request.form.get('time')
        team_size = request.form.get('team_size')
        contact_name = request.form.get('contact_name')
        contact_phone = request.form.get('contact_phone')

        file = request.files.get('file')
        filename = None
        if file:
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

        group = Group(
            spot_id=spot_id,
            date=date,
            time=time,
            team_size=team_size,
            contact_name=contact_name,
            contact_phone=contact_phone,
            excel_file=filename,
            user_id=user.id  # 关联当前用户
        )
        db.session.add(group)
        db.session.commit()
        return redirect(url_for('groups'))

    return render_template('group_sure.html', spot_id=spot_id)


@app.route('/order')
def order():
    return render_template('order.html')

@app.route('/my')
def my():
    return render_template('my.html')
@app.route('/collect_orders')
def collect_orders():
    # 查询 is_favorited 为 1 的数据
    favorited_spots = ScenicSpot.query.filter_by(is_favorited=True).all()
    return render_template('collect_orders.html', spots=favorited_spots)

# 预约订单
@app.route('/book_orders')
def book_orders():
    # 获取今天的日期
    today = datetime.now().date()

    # 查询状态不为 "已取消" 的预约记录
    appointments = db.session.query(Appointment, ScenicSpot).join(ScenicSpot, Appointment.spot_id == ScenicSpot.id).filter(
        Appointment.date >= today, Appointment.status != '已取消').all()

    return render_template('book_orders.html', appointments=appointments)

@app.route('/ticket_delete/<int:appointment_id>', methods=['POST'])
def ticket_delete(appointment_id):
    appointment = Appointment.query.get(appointment_id)
    if appointment:
        appointment.status = '已取消'
        db.session.commit()
        return jsonify({'message': '订单已取消'}), 200
    else:
        return jsonify({'message': '订单未找到'}), 404

@app.route('/appointments')
def appointments():
    appointments = Appointment.query.all()
    return render_template('appointments.html', appointments=appointments)

# 完成订单
@app.route('/complete_orders')
def complete_orders():
    # 获取当前用户的 ID
    user_id = session.get('user_id')
    
    # 如果用户未登录，提示登录并重定向
    if not user_id:
        flash('请先登录', 'warning')
        return redirect(url_for('login'))
    
    # 获取今天的日期
    today = datetime.now().date()

    # 查询当前用户且日期小于今天的预约记录，状态不为已取消
    appointments = db.session.query(Appointment, ScenicSpot).join(ScenicSpot, Appointment.spot_id == ScenicSpot.id).filter(
        Appointment.date < today, 
        Appointment.status != '已取消',
        Appointment.user_id == user_id  # 仅查询当前用户的预约记录
    ).all()

    return render_template('complete_orders.html', appointments=appointments)

# 取消订单
@app.route('/cancel_orders')
def cancel_orders():
    # 获取当前用户的 ID
    user_id = session.get('user_id')
    
    # 如果用户未登录，提示登录并重定向
    if not user_id:
        flash('请先登录', 'warning')
        return redirect(url_for('login'))
    
    # 查询当前用户且状态为已取消的预约记录
    appointments = db.session.query(Appointment, ScenicSpot).join(ScenicSpot, Appointment.spot_id == ScenicSpot.id).filter(
        Appointment.status == '已取消',
        Appointment.user_id == user_id  # 仅查询当前用户的预约记录
    ).all()

    return render_template('cancel_orders.html', appointments=appointments)


@app.route('/book_groups')
def book_groups():
    # 获取当前用户的 ID
    user_id = session.get('user_id')
    
    # 如果用户未登录，提示登录并重定向
    if not user_id:
        flash('请先登录', 'warning')
        return redirect(url_for('login'))
    
    # 查询当前用户的团票预约记录
    groups = db.session.query(Group, ScenicSpot).join(ScenicSpot, ScenicSpot.id == Group.spot_id).filter(
        Group.user_id == user_id  # 仅查询当前用户的团票记录
    ).all()
    
    return render_template('book_groups.html', groups=groups)


@app.route('/cancel_group/<int:group_id>', methods=['DELETE'])
def cancel_group(group_id):
    # 查找并删除对应的预约记录
    group = Group.query.get(group_id)
    if group:
        try:
            db.session.delete(group)
            db.session.commit()
            return jsonify({"success": True})
        except Exception as e:
            db.session.rollback()
            print(f"删除预约时出错: {e}")
            return jsonify({"success": False, "error": str(e)}), 500
    else:
        return jsonify({"success": False, "error": "未找到该预约记录"}), 404

# 我的页面功能按钮路由


@app.route('/change_password', methods=['GET', 'POST'])
def change_password():
    if request.method == 'POST':
        username= request.form.get('username')
        password= request.form.get('password')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')

        # 1. 查找用户是否存在
        user = User.query.filter_by(username=username).first()
        if user is None:
            flash('用户不存在，请确认账号是否正确！', 'danger')
            return render_template('change_password.html')
        # 2. 判断原密码是否与账号匹配
        if not check_password_hash(user.password, password):
            flash('原密码输入错误！', 'danger')
            return render_template('change_password.html')

        # 3. 判断两次密码是否一致
        if new_password != confirm_password:
            flash('两次密码输入不一致！', 'danger')
            return render_template('change_password.html')

        # 更新用户密码
        user.password = generate_password_hash(new_password)
        db.session.commit()
        flash('密码已重置，请重新登录。', 'success')
        return redirect(url_for('login'))

    return render_template('change_password.html')

@app.route('/bind_info', methods=['GET', 'POST'])
def bind_info():
    if request.method == 'POST':
        name = request.form.get('name')
        idcard = request.form.get('idcard')  
        type = request.form.get('type')
        user_id = session.get('user_id')  # 获取当前登录的用户ID
        existing_message = Message.query.filter_by(idcard=idcard).first()

        # 输入验证逻辑
        if not name:
            flash('姓名不能为空！', 'danger')
        elif not idcard:
            flash('身份证号码不能为空！', 'danger')
        elif existing_message:
            flash('该用户信息已存在！', 'danger')
        else:
            # 保存新用户绑定信息到数据库
            new_message = Message(name=name, idcard=idcard, type=type, user_id=user_id)  # 关联当前用户
            db.session.add(new_message)
            db.session.commit()
            flash('绑定成功。', 'success')
            return redirect(url_for('my'))
    return render_template('bind_info.html')




@app.route('/existing_info')
def existing_info():
    # 获取当前登录用户的ID
    user_id = session.get('user_id')

    # 如果没有登录，重定向到登录页面
    if not user_id:
        flash('请先登录', 'danger')
        return redirect(url_for('login'))

    # 查询当前用户的绑定信息
    messages = Message.query.filter_by(user_id=user_id).all()

    # 返回当前用户的绑定信息
    return render_template('existing_info.html', messages=messages)




@app.route('/logout')
def logout():
    session.clear()  # 清空所有会话数据
    flash('您已成功登出', 'success')
    return redirect(url_for('login'))


@app.route('/delete_account', methods=['GET', 'POST'])
def delete_account():
    if request.method == 'POST':
        if 'user_id' in session:
            user_id = session['user_id']
            user = User.query.get(user_id)
            if user:
                try:
                    # 删除用户相关的记录
                    db.session.query(Message).filter_by(user_id=user.id).delete()
                    db.session.query(Appointment).filter_by(user_id=user.id).delete()
                    db.session.query(Group).filter_by(user_id=user.id).delete()
                    db.session.delete(user)
                    db.session.commit()

                    session.pop('user_id', None)  # 清除 session
                    flash("账户已成功删除", "success")
                except Exception as e:
                    db.session.rollback()
                    flash(f"错误: {str(e)}", "danger")
            else:
                flash("未找到用户", "warning")
        else:
            flash("你未登录", "warning")
    return redirect(url_for('login'))



if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 创建数据库表
    app.run(debug=True)
